package com.jy.rhin.application.basic;

import cn.org.chiss.rhin._2015.basic.audit.AuditMessage;
import com.jy.rhin.application.assembler.AuditAssembler;
import com.jy.rhin.config.ws.WsServiceProperties;
import com.jy.rhin.domain.audit.AuditInfoDomainService;
import com.jy.rhin.domain.registration.InfraValueSetService;
import com.jy.rhin.facade.dto.SaveExternalSystemAuditInfoEvent;
import com.jy.rhin.facade.infra.controller.audit.assembler.AuditInfoAssembler;
import com.jy.rhin.sdk.dto.audit.AuditWrapperDto;
import com.jy.rhin.support.aspect.AuditLog;
import com.jy.rhin.support.interceptor.AuditInfoConvertFactory;
import com.jy.rhin.support.interceptor.SaveAuditInfoEvent;
import com.jy.rhin.support.interceptor.convertor.AuditInfoConverter4ExternalSystem;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Description:
 * @Author: lww
 * @Date: 2022/5/19 15:58
 */
@Slf4j
@Service
public class AuditService {

    @Resource
    AuditInfoDomainService auditInfoDomainService;
    @Resource
    InfraValueSetService infraValueSetService;
    @Resource
    AuditInfoConvertFactory convertFactory;
    @Resource
    WsServiceProperties wsServiceProperties;
    @Resource
    AuditInfoConverter4ExternalSystem auditInfoConverter4ExternalSystem;

    /**
     * 监听保存审计记录事件
     * 需要上报审计信息的接口，都需要加上自定义注解{@link AuditLog} ，在切面中，把出入参存入上下文，此时会标记 数据已经缓存。
     * 当数据已经缓存，则 从上线文获取原始xml及出/入参，打包审计记录信息，调用保存接口
     *
     * @param event
     */
    @SuppressWarnings("unused")
    @EventListener
    @Async
    public void onAuditInfo(SaveAuditInfoEvent event) {
        if (Boolean.FALSE.equals(wsServiceProperties.getAudit())) {
            log.debug("===ws服务端审计记录上报已关闭, 忽略本次审计事件===");
            return;
        }
        if (event.isCached()) {
            Object data = event.getData();
            String xml = event.getXml();
            AuditWrapperDto dto = convertFactory.convert(event);
            dto.setXmlText(xml);
            dto.getObjectDtoList().forEach(auditObjectDto -> auditObjectDto.getMiaoShu().setValue(xml));
            try {
               auditInfoDomainService.save(AuditInfoAssembler.toDO(dto), infraValueSetService.checkValueField(dto));
            } catch (Exception ex) {
                log.error("ws服务端审计记录上报异常", ex);
            }

        }
    }

    /**
     * 添加审计记录
     *
     * @param auditMessage
     */
    public Long addAuditLog(AuditMessage auditMessage) {
        AuditWrapperDto dto = AuditAssembler.toDto(auditMessage);
        return auditInfoDomainService.save(AuditInfoAssembler.toDO(dto), infraValueSetService.checkValueField(dto));
    }

    /**
     * 外部系统互相调用的请求和响应审计日志
     * @param event
     * @return
     */
    public void addAuditLog4ExternalSystem(SaveExternalSystemAuditInfoEvent event) {
        try {
            AuditWrapperDto dto = auditInfoConverter4ExternalSystem.convertReq(event);
            dto.setXmlText(event.getRuCan());
            dto.getObjectDtoList().forEach(auditObjectDto -> auditObjectDto.getMiaoShu().setValue(event.getRuCan()));
            auditInfoDomainService.save(AuditInfoAssembler.toDO(dto), infraValueSetService.checkValueField(dto));

            dto = auditInfoConverter4ExternalSystem.convertResp(event);
            dto.setXmlText(event.getChuCan());
            dto.getObjectDtoList().forEach(auditObjectDto -> auditObjectDto.getMiaoShu().setValue(event.getChuCan()));
            auditInfoDomainService.save(AuditInfoAssembler.toDO(dto), infraValueSetService.checkValueField(dto));
        } catch (Exception ex) {
            log.error("ws服务端审计记录上报异常", ex);
        }
    }


}
